#include "napi/native_api.h"
#include "module/udp.h"
#include <cstdint>
#include <string.h>


#include <stdlib.h>
#include "hilog/log.h"
#include "udp.h"
#include "queue.h"

static napi_value Add(napi_env env, napi_callback_info info)
{
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    napi_valuetype valuetype1;
    napi_typeof(env, args[1], &valuetype1);

    double value0;
    napi_get_value_double(env, args[0], &value0);

    double value1;
    napi_get_value_double(env, args[1], &value1);

    napi_value sum;
    napi_create_double(env, value0 + value1, &sum);
    
    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Add", "Add end111");

    return sum;

}

/*
static napi_value Udp_send(napi_env env, napi_callback_info info)
{
    //OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xffff, "Udp_recv", "Udp_send end111");
    
    //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "Udp_recv end111");
    size_t argc = 4;
    
    napi_status status;
    
    size_t length;
    
    //napi_value params[10] = {nullptr};
    
    napi_value args[4] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
    
    napi_valuetype valuetype0;
    napi_typeof(env, args[1], &valuetype0);
    
    //char ip[20];

    int port;
    
    napi_get_value_int32(env, args[1], &port);
    
    int socket = 0;
    
    status = napi_get_value_string_utf8(env, args[0], NULL, 0, &length);
    if (status != napi_ok) {
        // 错误处理
    }

    // 分配足够的内存来存储字符串
    char *ip = (char *)malloc(length + 1);
    if (ip == NULL) {
        // 内存分配失败处理
    }
    
     // 再次获取字符串，这次带上足够的内存
    status = napi_get_value_string_utf8(env, args[0], ip, length + 1, &length);
    if (status != napi_ok) {
        // 错误处理
    }
    
    
    // 检查参数是否为 ArrayBuffer
    bool is_array;
    
    size_t array_length;
    status = napi_is_arraybuffer(env, args[2], &is_array);
    if (status != napi_ok || !is_array)
        return NULL;

    void *data;
    status = napi_get_arraybuffer_info(env, args[2], &data, &array_length);
    if (status != napi_ok)
        return NULL;
    
    
    napi_typeof(env, args[3], &valuetype0);
    
    //char ip[20];

    int size;
    
    napi_get_value_int32(env, args[3], &size);
    
    //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "Udp_recv end222 %{public}s %{public}d %{public}d", ip, port, size);
    send_udp_data(ip, port,(char*)data,size);
    
    free(ip);
    
    napi_value sum;
    
    sum = 0;
    
    napi_create_int32(env, socket, &sum);
    
    return sum;
    
}
*/
static napi_value Udp_send(napi_env env, napi_callback_info info)
{
    //OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xffff, "Udp_recv", "Udp_send end111");
    
    //OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "Udp_recv end111");
    size_t argc = 5;
    
    napi_status status;
    
    size_t length;
    
    //napi_value params[10] = {nullptr};
    
    napi_value args[5] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
    
    napi_valuetype valuetype0;
    napi_typeof(env, args[1], &valuetype0);
    
    //char ip[20];

    int port;
    
    napi_get_value_int32(env, args[1], &port);
    
    int socket = 0;
    
    status = napi_get_value_string_utf8(env, args[0], NULL, 0, &length);
    if (status != napi_ok) {
        // 错误处理
    }

    // 分配足够的内存来存储字符串
    char *ip = (char *)malloc(length + 1);
    if (ip == NULL) {
        // 内存分配失败处理
    }
    
     // 再次获取字符串，这次带上足够的内存
    status = napi_get_value_string_utf8(env, args[0], ip, length + 1, &length);
    if (status != napi_ok) {
        // 错误处理
    }
    
    
    // 检查参数是否为 ArrayBuffer
    bool is_array;
    
    size_t array_length;
    status = napi_is_arraybuffer(env, args[2], &is_array);
    if (status != napi_ok || !is_array)
        return NULL;

    void *data;
    status = napi_get_arraybuffer_info(env, args[2], &data, &array_length);
    if (status != napi_ok)
        return NULL;
    
    
    napi_typeof(env, args[3], &valuetype0);
    
    //char ip[20];

    int size;
    
    napi_get_value_int32(env, args[3], &size);
    
    
    napi_typeof(env, args[4], &valuetype0);
    
    //char ip[20];

    int socket1;
    
    napi_get_value_int32(env, args[4], &socket1);
    
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "Udp_recv end222 %{public}s %{public}d %{public}d %{public}d" , ip, port, size, socket1);
    send_udp(socket1, ip, port,(char*)data,size);
    
    free(ip);
    
    napi_value sum;
    
    sum = 0;
    
    napi_create_int32(env, socket, &sum);
    
    return sum;
    
}

static napi_value Udp_create(napi_env env, napi_callback_info info)
{
    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Udp_recv", "Udp_recv end111"); 
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
    
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);
    

    int port;
    
    int socket = 0;
    
    napi_get_value_int32(env, args[0], &port);
    
    socket = create_udp(port);
    
    
    napi_value sum;
    
    napi_create_int32(env, socket, &sum);
    
    return sum;
    
}



static napi_value Udp_close(napi_env env, napi_callback_info info)
{
    OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Udp_recv", "Udp_recv end111");
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
    
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);
    
    
    int socket = 0;
    
    napi_get_value_int32(env, args[0], &socket);
    
    socket = close_udp(socket);
    
    
    
    
    napi_value sum;
    
    napi_create_int32(env, 0, &sum);
    
    return sum;
    
}


static napi_value Udp_recv(napi_env env, napi_callback_info info)
{
    //OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Udp_recv", "Udp_recv end111");
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);
    

    int port;
    napi_get_value_int32(env, args[0], &port);

    
    int recv_len = 0;
    
    Message* buf = NULL;
    
    napi_value output_array;
    
    void *output_ptr = NULL;
    
    napi_value output_buffer;
   
    
   // OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "Udp_recv", "Udp_recv end");
    
    buf = recv_udp_data_queue(port);
    
    /*
    if(recv_len <= 0){
        
         napi_create_arraybuffer(env, 4, &output_ptr, &output_buffer);
    

        napi_create_typedarray(env, napi_uint8_array, 4, output_buffer, 0, &output_array);
        return output_array;
    }
    */
    
    if(buf == NULL){
        napi_create_arraybuffer(env, 4, &output_ptr, &output_buffer);
    

        napi_create_typedarray(env, napi_uint8_array, 4, output_buffer, 0, &output_array);
        return output_array;
    }
    
    //napi_create_arraybuffer(env, buf->data_size + 4, &output_ptr, &output_buffer);
    

    //napi_create_typedarray(env, napi_uint8_array, buf->data_size + 4, output_buffer, 0, &output_array);
    
     napi_create_arraybuffer(env, buf->data_size, &output_ptr, &output_buffer);
    

    napi_create_typedarray(env, napi_uint8_array, buf->data_size, output_buffer, 0, &output_array);
    
    int32_t len = buf->data_size;
    
    //memcpy(output_ptr, &len, 4);
    
   // memcpy((char *)output_ptr + 4, buf->data, len);
    
    memcpy((char *)output_ptr, buf->data, len);
    
    mq_free_message(buf);
    

    return output_array;

}

/*
static napi_value Udp_recv(napi_env env, napi_callback_info info)
{
    //OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Udp_recv", "Udp_recv end111");
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);
    

    int port;
    napi_get_value_int32(env, args[0], &port);

    
    int recv_len = 0;
    
    char *buf;
    
    napi_value output_array;
    
    void *output_ptr = NULL;
    
    napi_value output_buffer;
   
    
    //OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xff00, "Udp_recv", "Udp_recv end");
    buf = recv_udp_data(port, &recv_len);
    
    if(recv_len <= 0){
        
         napi_create_arraybuffer(env, 4, &output_ptr, &output_buffer);
    

        napi_create_typedarray(env, napi_uint8_array, 4, output_buffer, 0, &output_array);
        return output_array;
    }
    
    
    
    
    napi_create_arraybuffer(env, recv_len + 4, &output_ptr, &output_buffer);
    

    napi_create_typedarray(env, napi_uint8_array, recv_len + 4, output_buffer, 0, &output_array);
    
    int32_t len = recv_len;
    
    memcpy(output_ptr, &len, 4);
    
    memcpy((char *)output_ptr + 4, buf, recv_len);
    
    delete(buf);
    

    return output_array;

}
*/

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "udp_create", nullptr, Udp_create, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "udp_close", nullptr, Udp_close, nullptr, nullptr, nullptr, napi_default, nullptr },
         { "udp_recv", nullptr, Udp_recv, nullptr, nullptr, nullptr, napi_default, nullptr },
         { "udp_send", nullptr, Udp_send, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "udp_lib",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterUdpModule(void)
{
    napi_module_register(&demoModule);
}
